#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <netinet/ip_icmp.h>
#include <sys/socket.h>

unsigned short checksum(void *buf, int len)
{
	short *b = buf;
	int sum;
	for (sum = 0; len; len -= 2)
		sum += *b++;
	sum = (sum >> 16) + (short) sum;
	sum += sum >> 16;
	return ~sum;
}

int main(int argc, char *argv[])
{
	long n;
	int c = 1;
	if (argc < 2)
		return EINVAL;
	if (argc > 2)
	if ((c = strtol(argv[2], NULL, 10)) < 1)
		return EINVAL;
	int s = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP);
	if (s < 0) return errno;
	struct timeval time;
	time.tv_sec  = 0;
	time.tv_usec = 1;
	n = setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &time, sizeof(time));
	if (n < 0) return errno;
	n = setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &time, sizeof(time));
	if (n < 0) return errno;
	struct addrinfo hints = {0}, *addr0;
	hints.ai_family = AF_INET;
	hints.ai_socktype = SOCK_RAW;
	hints.ai_protocol = IPPROTO_ICMP;
	if (n = getaddrinfo(argv[1], NULL, &hints, &addr0))
		return n;

	struct icmp icmp = {0};
	icmp.icmp_type = ICMP_ECHO;
	icmp.icmp_seq = htons(1);
	icmp.icmp_cksum = checksum(&icmp, ICMP_MINLEN);

	do
	{
		struct timespec t, r;
		clock_gettime(CLOCK_MONOTONIC, &t);
		n = sendto(s, &icmp, ICMP_MINLEN, 0, addr0->ai_addr, addr0->ai_addrlen);
		if (n < 0)
		{
			perror("sendto");
			continue;
		}
		char buffer[8];
		n = recv(s, buffer, sizeof(buffer), 0);
		if (n < 0)
		{
			perror("recv");
			continue;
		}
		clock_gettime(CLOCK_MONOTONIC, &r);
		n = (r.tv_sec - t.tv_sec) * 1000000000 + r.tv_nsec - t.tv_nsec;
		if (n > 1000000000)
		{
			fprintf(stderr, "%ld\n", n);
			continue;
		}
		printf("%ld\n", n);
	} while (--c);
	freeaddrinfo(addr0);
	close(s);
	return 0;
}
